/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui;

import business.GpsRecords;
import com.toedter.calendar.JCalendar;
import data.Connection;
import data.GPSRecordTable;
import data.TrainingTable;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dialog.ModalExclusionType;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.plaf.basic.BasicSplitPaneUI.BasicHorizontalLayoutManager;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;

/**
 *
 * @author stana
 */
public class MainWindow extends JFrame
{

    private JMenuBar menuBar;
    private JMenu fileMenu;
    private JMenuItem exitMenuItem;
    private JMenu helpMenu;
    private JMenuItem aboutMenuItem;
    private JTextArea descriptionText;
    private JCalendar calendar;
    private TrainingTable trainingTable;
    private GPSRecordTable gpsRecordTable;
    private Date previousDate;
    private JButton loadGpsButton;
    private JButton deleteGpsButton;
    private JButton showTrackMapButton;
    private JPanel gpsChartsPanel;
    private JPanel labelsPanel;
    private File lastDirectory;//kvuli pameti open file dialogu
    private GpsRecords gpsRecords;
    private Chart altitudeChart;
    private JPanel altitudePanel;
    private Chart speedChart;
    private JPanel speedPanel;
    private JLabel timeLabel;
    private JLabel averageLabel;
    private JLabel upMeterLabel;
    private JLabel downMeterLabel;
    private JLabel distanceLabel;
    private Properties properties;
    private String propertiesFileName;
    private String databaseFileName;
    private Connection connection;

    public MainWindow()
    {
        propertiesFileName = "trenink.properties";
        databaseFileName="data.db";
        loadProperties();
        connection=Connection.getInstance();
        connection.setDatabaseFileName(databaseFileName);
        connection.conenctDatabase();   
        trainingTable = new TrainingTable();
        gpsRecordTable = new GPSRecordTable();
        
        //setExtendedState(MAXIMIZED_BOTH);
        
          
        initComponents();
        previousDate = calendar.getDate();
    }

    private void loadProperties()
    {
        properties = new Properties();
        try
        {
            properties.load(new FileInputStream(propertiesFileName));
        } catch (IOException e)
        {
            File file = new File(propertiesFileName);
            try
            {
                file.createNewFile();
            } catch (IOException ex)
            {
                Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        lastDirectory = new File(properties.getProperty("lastDirectory",""));
        databaseFileName=properties.getProperty("databaseFileName", "data.db");
    }

    private void initComponents()
    {

        menuBar = new JMenuBar();
        fileMenu = new JMenu("Soubor");
        exitMenuItem = new JMenuItem("Konec");
        helpMenu = new JMenu("Nápověda");
        aboutMenuItem = new JMenuItem("O programu");
        fileMenu.add(exitMenuItem);
        menuBar.add(fileMenu);
        menuBar.add(helpMenu);
        helpMenu.add(aboutMenuItem);
        setJMenuBar(menuBar);


        calendar = new JCalendar();
        descriptionText = new JTextArea();
        timeLabel = new JLabel("Celkový čas: ");
        distanceLabel = new JLabel("Celková vzdálenost: ");
        averageLabel = new JLabel("Průměrná rychlost: ");
        upMeterLabel = new JLabel("Nastoupané metry: ");
        downMeterLabel = new JLabel("Naklesané metry: ");
        loadGpsButton = new JButton("Nahrát gpx soubor");
        deleteGpsButton = new JButton("Smazat GPS data");
        showTrackMapButton = new JButton("Zobrazit trasu na mapě");
        labelsPanel = new JPanel();
        labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.PAGE_AXIS));
        labelsPanel.add(timeLabel);
        labelsPanel.add(distanceLabel);
        labelsPanel.add(averageLabel);
        labelsPanel.add(upMeterLabel);
        labelsPanel.add(downMeterLabel);


        altitudeChart = new Chart("Profil trati", "Dráha(m)", "Nadmořská výška(m)", "Nadmořská výška");
        speedChart = new Chart("Potřebný čas na kilometr", "Dráha(m)", "Čas na km(minuta/km)", "Čas na kilometr");

        gpsRecords = new GpsRecords(trainingTable.getGPSRecord(calendar.getDate()));
        altitudePanel = altitudeChart.getPanel(gpsRecords.getAltitudeList());
        speedPanel = speedChart.getPanel(gpsRecords.getSpeedList());
        gpsChartsPanel = new JPanel(new GridLayout(0, 2));
        gpsChartsPanel.add(altitudePanel);
        gpsChartsPanel.add(speedPanel);


        Container pane = getContentPane();
        pane.setLayout(new GridBagLayout());
        GridBagConstraints gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.weighty = 0.2;
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
        pane.add(calendar, gridBagConstraints);

        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.weightx = 1;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.anchor = GridBagConstraints.CENTER;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        pane.add(descriptionText, gridBagConstraints);

        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridheight = 1;
        gridBagConstraints.gridwidth = 1;
        gridBagConstraints.weightx = 0;
        gridBagConstraints.weighty = 0;
        gridBagConstraints.fill = GridBagConstraints.NONE;
        gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
        pane.add(labelsPanel, gridBagConstraints);

        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        //gridBagConstraints.anchor=GridBagConstraints.LINE_START;
        pane.add(loadGpsButton, gridBagConstraints);

        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_END;
        //pane.add(deleteGpsButton, gridBagConstraints);

        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
        //pane.add(showTrackMapButton, gridBagConstraints);
        pane.add(deleteGpsButton, gridBagConstraints);

        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.weighty = 0.6;
//        gridBagConstraints.gridheight=2;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        //gridBagConstraints.anchor=GridBagConstraints.CENTER;
        pane.add(gpsChartsPanel, gridBagConstraints);

//

        aboutMenuItem.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                aboutMenuItemClicked();
            }
        });

        exitMenuItem.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                exitApplication();
            }
        });

        calendar.addPropertyChangeListener(new PropertyChangeListener()
        {

            @Override
            public void propertyChange(PropertyChangeEvent evt)
            {
                dateChanged();
            }
        });
        loadGpsButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                loadGpsButtonClicked();
            }
        });
        deleteGpsButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                int trainingId = trainingTable.getIndex(calendar.getDate());
                gpsRecordTable.deleteData(trainingId);
                dateChanged();
            }
        });

        showTrackMapButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                TrackWindow tr = new TrackWindow(new Date());
                tr.setModal(true);
                tr.setVisible(true);
            }
        });

        addWindowListener(new WindowListener()
        {

            @Override
            public void windowOpened(WindowEvent e)
            {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void windowClosing(WindowEvent e)
            {
                exitApplication();

                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void windowClosed(WindowEvent e)
            {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void windowIconified(WindowEvent e)
            {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void windowDeiconified(WindowEvent e)
            {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void windowActivated(WindowEvent e)
            {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void windowDeactivated(WindowEvent e)
            {
                //throw new UnsupportedOperationException("Not supported yet.");
            }
        });

        setBounds(200, 200, 500, 500);
        setVisible(true);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        setExtendedState(JFrame.MAXIMIZED_BOTH);

    }

    private void aboutMenuItemClicked()
    {
        JOptionPane.showMessageDialog(this, "Program tréninkový denník", "O programu", JOptionPane.INFORMATION_MESSAGE);
    }

    private void exitApplication()
    {
        int i = JOptionPane.showConfirmDialog(this, "Opravdu chcete skončit?",
                "Konec", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
        if (i == JOptionPane.YES_OPTION)
        {
            dateChanged();
            saveProperties();
            connection.closeConnection();
            System.exit(0);
        }

        //System.exit(0);
    }

    private void saveProperties()
    {
        properties.setProperty("lastDirectory", lastDirectory.getAbsolutePath());
        properties.setProperty("databaseFileName", databaseFileName);                
        try
        {
            properties.store(new FileOutputStream(propertiesFileName), null);
        } catch (IOException ex)
        {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void loadGpsButtonClicked()
    {
        File file = new File("");
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setCurrentDirectory(lastDirectory);
        int returnValue = fileChooser.showDialog(this, "Nahrát");
        if (returnValue == JFileChooser.APPROVE_OPTION)
        {
            file = fileChooser.getSelectedFile();
            //This is where a real application would open the file.
            importFile(file);
            lastDirectory = fileChooser.getCurrentDirectory();
        } else
        {
            lastDirectory = fileChooser.getCurrentDirectory();
        }

    }

    private void importFile(File file)
    {
        int trainingId = trainingTable.getIndex(calendar.getDate());
        if (trainingId == 0)
        {
            trainingTable.insertData(calendar.getDate(), "");
            trainingId = trainingTable.getIndex(calendar.getDate());
        }
        try
        {
            Document document = new SAXBuilder().build(file);
            Namespace namespace = Namespace.getNamespace("http://www.topografix.com/GPX/1/0");
            Element el = document.getRootElement().getChild("trk", namespace).getChild("trkseg", namespace);
            List<Element> list = el.getChildren("trkpt", namespace);
            gpsRecordTable.insertList(list, trainingId);

        } catch (Exception ex)
        {
            JOptionPane.showMessageDialog(this, "Data nelze načíst, zkontrolujte"
                    + " prosím, jesti je soubor ve správném formátu", "Chyba",
                    JOptionPane.ERROR_MESSAGE);
        }
        dateChanged();

    }

    private void dateChanged()
    {
        try
        {
            trainingTable.setDescription(previousDate, descriptionText.getText());
        } catch (SQLException ex)
        {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
        descriptionText.setText(trainingTable.getDescription(calendar.getDate()));
        previousDate = calendar.getDate();
        if (trainingTable.haveRecord(calendar.getDate()))
        {
            loadGpsButton.setEnabled(false);
            deleteGpsButton.setEnabled(true);
            showTrackMapButton.setEnabled(true);
        } else
        {
            loadGpsButton.setEnabled(true);
            deleteGpsButton.setEnabled(false);
            showTrackMapButton.setEnabled(false);
        }
        gpsChartsPanel.remove(altitudePanel);
        gpsChartsPanel.remove(speedPanel);
        gpsRecords = new GpsRecords(trainingTable.getGPSRecord(calendar.getDate()));
        updateLabels(gpsRecords);
        altitudePanel = altitudeChart.getPanel(gpsRecords.getAltitudeList());
        speedPanel = speedChart.getPanel(gpsRecords.getSpeedList());
        gpsChartsPanel.add(altitudePanel, 0);
        gpsChartsPanel.add(speedPanel, 1);
        getContentPane().validate();
        getContentPane().repaint();

    }

    private void updateLabels(GpsRecords gpsRecords)
    {
        double s = gpsRecords.getDistance();
        double t = gpsRecords.getTotalTime();
        double v = s / t;
        if (Double.isNaN(v))
        {
            v = 0;
        }
        distanceLabel.setText("Celková vzálenost: " + roundToString(s) + "m");
        timeLabel.setText("Celkový čas: " + getTimeString(t));
        averageLabel.setText("Průměrná rychlosti: " + roundToString(v * 3.6) + "km/h");
        upMeterLabel.setText("Celkové stoupání: " + roundToString(gpsRecords.getUpMeters()) + "m");
        downMeterLabel.setText("Celkové klesání: " + roundToString(gpsRecords.getDownMeters()) + "m");
    }

    private String roundToString(double value)
    {
        return String.valueOf(Math.round(value * 100.0) / 100.0);
    }

    private String getTimeString(double t)
    {
        double help;
        int hour = (int) (t / 3600);
        help = t / 3600 - hour;
        int min = (int) Math.floor(help * 60);
        help = (help * 60) - min;
        int sec = (int) Math.floor(help * 60);
        return String.valueOf(hour) + "h" + String.valueOf(min) + "min" + String.valueOf(sec) + "s";
    }
}
